<?php
// +-------------------------------------------------------------------
// | 
// +-------------------------------------------------------------------
// | Copyright (c) 2009-2016 All rights reserved.
// +-------------------------------------------------------------------
namespace Think\Log\Driver;

class Local
{

    protected $now = '';

    protected $logPath = '';

    protected $ip = '';

    protected $logCenterPath = '/tmp/app_log';

    protected $logCenterTags = array(
            'APP',
            'ERR'
    );

    protected $routeErrorMessages = array();

    public function write ($log, $destination = '', $logItems = array())
    {
        $this->now = date('Y-m-d H:i:s', NOW_TIME);
        $this->logPath = ROOT_PATH . LOG_PATH;
        $this->ip = get_client_ip(0, true);
        
        $this->_saveSystemLog($logItems);
        $this->_saveCenterLog($logItems);
    }
    
    // 通用日志
    protected function _saveSystemLog ($logItems)
    {
        $destination = $this->logPath . date('y_m_d') . '.php';
        
        // 每个日志文件最大 1M
        if (is_file($destination) && (1024 * 1024 <= filesize($destination)))
        {
            $st = copy($destination, dirname($destination) . '/' . substr(basename($destination), 0, - 4) . '_[' . date('H:i:s') . '].php');
            $st and unlink($destination);
        }
        
        // 记录性能信息
        $dbWrite = $GLOBALS['_DB_SET_CONTER_'] ?  : 0;
        $dbRead = $GLOBALS['_DB_GET_CONTER_'] ?  : 0;
        $cacheWrite = $GLOBALS['_CACHE_SET_CONTER_'] ?  : 0;
        $cacheRead = $GLOBALS['_CACHE_GET_CONTER_'] ?  : 0;
        $logItems[] = array(
                'PROFILE',
                "DB WRITE : $dbWrite / DB READ : $dbRead / CACHE WRITE : $cacheWrite / CACHE READ : $cacheRead",
                microtime(true)
        );
        
        $log = "[{$this->now}] " . $this->ip . ' ' . $_SERVER['REQUEST_METHOD'] . ' ' . $_SERVER['REQUEST_URI'] . "\r\n";
        file_exists($destination) or $log = "<?php exit();?>\r\n" . $log;
        foreach ($logItems as $v)
        {
            $tag = $v[0];
            $info = is_string($v[1]) ? $v[1] : json_encode($v[1]);
            list ($time, $micro) = explode('.', $v[2]);
            $timeStr = date('H:i:s', $time);
            $latency = ($time - NOW_TIME) * 1000 + number_format('0.' . $micro, 3) * 1000 ?  : 0;
            $latencyStr = $latency >= 1000 ? number_format($latency / 1000, 0) . 's' : $latency . 'ms';
            $log .= "[$tag] [+{$latencyStr}] $info\r\n";
        }
        $this->_write($destination, $log . "\r\n");
    }
    
    // 统计日志
    protected function _saveCenterLog ($logItems)
    {
        foreach ($logItems as $v)
        {
            in_array($v[0], $this->logCenterTags) and $log .= json_encode($this->_formartItem($v[0], $v[1])) . "\r\n";
        }
        
        $logDir = rtrim(defined('LOG_CENTER_PATH') && LOG_CENTER_PATH && strpos(LOG_CENTER_PATH, '/') === 0 ? LOG_CENTER_PATH : $this->logCenterPath, '/') . '/';
        $destination = $logDir . 'APP_' . date('y_m_d') . '.log';
        
        $this->_write($destination, $log);
    }
    
    // 写日志
    protected function _write ($destination, $log)
    {
        if ($log)
        {
            is_dir(dirname($destination)) or mkdir(dirname($destination), 0777, true);
            error_log($log, 3, $destination);
        }
    }
    
    // 格式化应用统计日志
    protected function _formartItem ($tag, $info)
    {
        $item['tag'] = $tag;
        $item['status'] = strtolower($item['status']) === 'ok' ? 'ok' : 'error';
        $item['time'] = $this->now;
        $item['ip'] = $this->ip;
        $item['request'] = $_SERVER['REQUEST_METHOD'] . ' : ' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];
        
        $this->routeErrorMessages = $this->routeErrorMessages ?  : array(
                L('_MODULE_NOT_EXIST_'),
                L('_CONTROLLER_NOT_EXIST_'),
                L('_ERROR_ACTION_')
        );
        
        is_array($info) or $info = array(
                'info' => $info
        );
        
        foreach ($info as $k => $v)
        {
            if ($k != 'tag' && $k != 'status' && $k != 'info')
            {
                $k = "info_" . $k;
            }
            $item[$k] = $v;
        }
        
        if ($item['info'])
        {
            foreach ($this->routeErrorMessages as $i)
            {
                if ($item['info'] && strpos($item['info'], $i) === 0)
                {
                    $item['tag'] = 'ROUTE';
                    break;
                }
            }
        }
        
        return $item;
    }
}